package com.rois.librois.libRoISMessageStorage;

import java.util.Vector;

import com.rois.librois.libRoISAppClient.ClientOperationImpl;

/**
 * Data holder class for Service Application.
 * This object holds CORBA client object and  a list of:
 * - connection status
 * - connecting CORBA server name
 * - CORBA naming service
 * - subscribed event messages
 * - bound components
 * - sent error messages
 *
 * @author Miki Sato <miki.sato.1225@gmail.com>
 *
 *    The MIT licence
 *
 *    Copyright (C) 2011
 *      ATR Intelligent Robotics and Communication Laboratories, Japan
 *
 *    Permission is hereby granted, free of charge, to any person obtaining a copy
 *    of this software and associated documentation files (the "Software"), to deal
 *    in the Software without restriction, including without limitation the rights
 *    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 *    of the Software, and to permit persons to whom the Software is furnished to do so,
 *    subject to the following conditions:
 *
 *    The above copyright notice and this permission notice shall be included in all
 *    copies or substantial portions of the Software.
 *
 *    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
 *    INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
 *    PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 *    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 *    OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 *    SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

public class RoIS_ServiceApps {
	public ClientOperationImpl client_p;

	private static final int DEFAULT_APP_MAXSIZE = 100;
	private static final int DEFAULT_TYPE_MAXSIZE = 100;
	private static final int DEFAULT_MSG_MAXSIZE = 100;
	public int size;
	public int max_size;
	public int max_cmd_size;
	public int max_evt_size;
	public int max_cmd_message_size;
	public int max_evt_message_size;
	public int max_err_message_size;

	public Vector<Boolean> connection = new Vector<Boolean>();
	public Vector<String> nameservice = new Vector<String>();
	public Vector<String> servername = new Vector<String>();

	public Vector<RoIS_RegisteredTypes> subscribed_events = new Vector<RoIS_RegisteredTypes>();
	public Vector<RoIS_RegisteredTypes> bound_components = new Vector<RoIS_RegisteredTypes>();
	public Vector<RoIS_ExchangedMessages> sent_errors = new Vector<RoIS_ExchangedMessages>();

	/**
	 * create Service App. data holder.
	 */
	public RoIS_ServiceApps()
	{
		client_p = null;
		max_size = DEFAULT_APP_MAXSIZE;
		max_cmd_size = DEFAULT_TYPE_MAXSIZE;
		max_evt_size = DEFAULT_TYPE_MAXSIZE;
		max_cmd_message_size = DEFAULT_MSG_MAXSIZE;
		max_evt_message_size = DEFAULT_MSG_MAXSIZE;
		max_err_message_size = DEFAULT_MSG_MAXSIZE;
		clear();
	}

	/**
	 * clear all data.
	 */
	public void clear()
	{
		if(client_p!=null)
		{
			client_p = null;
		}
		client_p = new ClientOperationImpl();

		size = 0;
		connection.clear();
		nameservice.clear();
		servername.clear();

		subscribed_events.clear();
		bound_components.clear();
		sent_errors.clear();
	}

	/**
	 * add Service App. at the end of service app. list.
	 * @param _connection connection status
	 * @param _nameservice CORBA naming service
	 * @param _servername CORBA server name
	 */
	public void push_back(
		boolean _connection,
		String _nameservice,
		String _servername
	)
	{
		connection.add(_connection);
		nameservice.add(_nameservice);
		servername.add(_servername);

		RoIS_RegisteredTypes _subscribed_events = new RoIS_RegisteredTypes();
		_subscribed_events.max_size = max_evt_size;
		_subscribed_events.max_message_size = max_evt_message_size;
		subscribed_events.add(_subscribed_events);

		RoIS_RegisteredTypes _bound_components = new RoIS_RegisteredTypes();
		_bound_components.max_size = max_cmd_size;
		_bound_components.max_message_size = max_cmd_message_size;
		bound_components.add(_bound_components);

		RoIS_ExchangedMessages _sent_errors = new RoIS_ExchangedMessages();
		_sent_errors.max_size = max_err_message_size;
		sent_errors.add(_sent_errors);

		size++;

		if(size>max_size)
		{
			erase(0);
		}
	}

	/**
	 * remove Service App. at the end of service app. list.
	 */
	public void pop_back()
	{
		if(size>0)
		{
			connection.remove(connection.size()-1);
			nameservice.remove(nameservice.size()-1);
			servername.remove(servername.size()-1);

			subscribed_events.remove(subscribed_events.size()-1);
			bound_components.remove(bound_components.size()-1);
			sent_errors.remove(sent_errors.size()-1);

			size--;
		}
	}

	/**
	 * remove specified service App. from service app. list.
	 * @param index index of the service app.
	 */
	public void erase(
		int index
	)
	{
		if(size>0)
		{
			connection.remove(index);
			nameservice.remove(index);
			servername.remove(index);
			subscribed_events.remove(index);
			bound_components.remove(index);
			sent_errors.remove(index);
			size--;
		}
	}

	/**
	 * get index of a service App. related to server name.
	 * @param _servername CORBA server name of the service app.
	 * @return index of the service app.
	 */
	public int getIndexByServername(
		String _servername
	)
	{
		int iRes = -1;
		for(int i=0; i<size; i++)
		{
			if(servername.get(i).matches(_servername))
			{
				iRes = i;
				break;
			}
		}
		return iRes;
	}

	/**
	 * get index of a service App. related to requested command message.
	 * @param component_ref reference ID of the component
	 * @param message_id message ID of the command
	 * @return index of the service app.
	 */
	public int getIndexByCompRefAndCommandId(
		String component_ref,
		String message_id
	)
	{
		int iRes = -1;
		for(int i=0; i<size; i++)
		{
			int com_index = bound_components.get(i).getIndexByReferenceId(component_ref);
			if(com_index!=-1)
			{
				int msg_size = bound_components.get(i).messages.get(com_index).size;
				for(int j=0; j<msg_size; j++)
				{
					String msg_index = bound_components.get(i).messages.get(com_index).id.get(j);
					if(msg_index.matches(message_id))
					{
						iRes = i;
						break;
					}
				}
			}
		}
		return iRes;
	}

	/**
	 * get index of a service App. related to subscribed event message.
	 * @param event_type event type of the event
	 * @param reference_id subscribed ID of the event
	 * @return index of the service app.
	 */
	public int getIndexByEventTypeAndSubscribeId(
		String event_type,
		String reference_id
	)
	{
		int iRes = -1;
		for(int i=0; i<size; i++)
		{
			int evt_index = subscribed_events.get(i).getIndexByReferenceId(reference_id);
			if(evt_index!=-1)
			{
				if(subscribed_events.get(i).type.get(evt_index).matches(event_type))
				{
					iRes = i;
					break;
				}
			}
		}
		return iRes;
	}

	/**
	 * get a list of index of service App. related to bound component.
	 * @param component_ref reference ID of the component
	 * @return list of index
	 */
	public Vector<Integer> getIndexListByCompRef(
		String component_ref
	)
	{
		Vector<Integer> iseqRes = new Vector<Integer>();
		iseqRes.clear();
		for(int i=0; i<size; i++)
		{
			int com_index = bound_components.get(i).getIndexByReferenceId(component_ref);
			if(com_index!=-1)
			{
				iseqRes.add(i);
			}
		}
		return iseqRes;
	}

	/**
	 * get index of bound component.
	 * @param servername CORBA server name of the service app.
	 * @param component_ref reference ID of the component
	 * @param component_index (out) index of the component
	 * @return true/false
	 */
	public boolean getBoundComponentIndex(
		String servername,
		String component_ref,
		int component_index
	)
	{
		int server_index = -1;
		server_index = getIndexByServername(servername);
		if(server_index==-1)
		{
			return false;
		}
		else
		{
			// search component
			component_index = -1;
			int size = bound_components.get(server_index).size;
			for(int i=0; i<size; i++)
			{
				if(bound_components.get(server_index).referenceid.get(i).matches(component_ref))
				{
					component_index=i;
					break;
				}
			}
			if(component_index==-1)
			{
				return false;
			}
		}
		return true;
	}

	/**
	 * chech availability of a component
	 * @param servername CORBA server name of the service app.
	 * @param component_ref reference ID of the component
	 * @return true/false
	 */
	public boolean checkComponentAvailability(
		String servername,
		String component_ref
	)
	{
		// check bind status for this service application
		int server_index = getIndexByServername(servername);
		if(server_index!=-1)
		{
			if(bound_components.get(server_index).getIndexByReferenceId(component_ref)!=-1)
			{
				return false;
			}
		}
		return true;
	}
}
